package com.fsz.pachong.pachong.util;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * - - - - - - - - - - - - - - - - - - 导出 </br>
 * 1.正规excel导出 (格式简单,数据量可以,5W以内吧) </br>
 * 注解方式: ExcelExportUtil.exportExcel(ExportParams entity, Class<?>
 * pojoClass,Collection<?> dataSet) </br>
 * 2.不定多少列,但是格式依然简单数据库不大 </br>
 * 自定义方式: ExcelExportUtil.exportExcel(ExportParams entity,
 * List<ExcelExportEntity> entityList,Collection<?> dataSet) </br>
 * 3.数据量大超过5W,还在100W以内 </br>
 * 注解方式 ExcelExportUtil.exportBigExcel(ExportParams entity, Class<?>
 * pojoClass,IExcelExportServer server, Object queryParams) </br>
 * 自定义方式: ExcelExportUtil.exportBigExcel(ExportParams entity,
 * List<ExcelExportEntity> excelParams,IExcelExportServer server, Object
 * queryParams) </br>
 * 4.样式复杂,数据量尽量别大 </br>
 * 模板导出 ExcelExportUtil.exportExcel(TemplateExportParams params, Map<String,
 * Object> map) </br>
 * 5.一次导出多个风格不一致的sheet </br>
 * 模板导出 ExcelExportUtil.exportExcel(Map<Integer, Map<String, Object>>
 * map,TemplateExportParams params) </br>
 * 6.一个模板但是要导出非常多份 </br>
 * 模板导出 ExcelExportUtil.exportExcelClone(Map<Integer, List<Map<String, Object>>>
 * map,TemplateExportParams params) </br>
 * 7.模板无法满足你的自定义,试试html </br>
 * 自己构造html,然后我给你转成excel ExcelXorHtmlUtil.htmlToExcel(String html, ExcelType
 * type) </br>
 * 8.数据量过百万级了.放弃excel吧,csv导出 </br>
 * 注解方式: CsvExportUtil.exportCsv(CsvExportParams params, Class<?> pojoClass,
 * OutputStream outputStream) </br>
 * 自定义方式: CsvExportUtil.exportCsv(CsvExportParams params,
 * List<ExcelExportEntity> entityList, OutputStream outputStream) </br>
 * 9.word导出 </br>
 * 模板导出: WordExportUtil.exportWord07(String url, Map<String, Object> map) </br>
 * 10.PDF导出 </br>
 * 模板导出: TODO </br>
 * 
 * </br>
 * - - - - - - - - - - - - - - - - - - 导入 </br>
 * 如果想提高性能 ImportParams 的concurrentTask 可以帮助并发导入,仅单行,最小1000 </br>
 * excel有单个的那种特殊读取,readSingleCell 参数可以支持 </br>
 * 1. 不需要检验,数据量不大(5W以内) </br>
 * 注解或者MAP: ExcelImportUtil.importExcel(File file, Class<?> pojoClass,
 * ImportParams params) </br>
 * 2. 需要导入,数据量不大 </br>
 * 注解或者MAP: ExcelImportUtil.importExcelMore(InputStream inputstream, Class<?>
 * pojoClass, ImportParams params) </br>
 * 3. 数据量大了,或者你有特别多的导入操作,内存比较少,仅支持单行 </br>
 * SAX方式 ExcelImportUtil.importExcelBySax(InputStream inputstream, Class<?>
 * pojoClass, ImportParams params, IReadHandler handler) </br>
 * 4. 数据量超过EXCEL限制,CSV读取 </br>
 * 小数据量: CsvImportUtil.importCsv(InputStream inputstream, Class<?>
 * pojoClass,CsvImportParams params) </br>
 * 大数据量: CsvImportUtil.importCsv(InputStream inputstream, Class<?>
 * pojoClass,CsvImportParams params, IReadHandler readHandler) </br>
 * 
 * </br>
 * </br>
 * - - - - - - 关于Excel导出XLS和XLSX区别</br>
 * 1.导出时间XLS比XLSX快2-3倍</br>
 * 2.导出大小XLS是XLSX的2-3倍或者更多</br>
 * 3.导出需要综合网速和本地速度做考虑</br>
 * </br>
 * 
 * 1.easypoi 父包--作用大家都懂得</br>
 * 2.easypoi-annotation 基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理</br>
 * 3.easypoi-base 导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能</br>
 * 4.easypoi-web 耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能</br>
 * 5.sax 导入使用xercesImpl这个包(这个包可能造成奇怪的问题哈),word导出使用poi-scratchpad,都作为可选包了</br>
 * 
 * @author ouda
 *
 */
public class EasyPoiExcelUtils {

	protected static final String HSSF = ".xls";
	protected static final String XSSF = ".xlsx";

	public static void sellerExportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,
			String fileName, HttpServletResponse response) {
		defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
	}

	/**
	 * 功能描述：复杂导出Excel，包括文件名以及表名。创建表头
	 *
	 * @param list
	 *            导出的实体类
	 * @param title
	 *            表头名称
	 * @param sheetName
	 *            sheet表名
	 * @param pojoClass
	 *            映射的实体类
	 * @param isCreateHeader
	 *            是否创建表头
	 * @param fileName
	 * @param response
	 * @return
	 */
	public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName,
			boolean isCreateHeader, HttpServletResponse response) {
		ExportParams exportParams = new ExportParams(title, sheetName);
		exportParams.setCreateHeadRows(isCreateHeader);
		defaultExport(list, pojoClass, fileName, response, exportParams);
	}

	/**
	 * 功能描述：复杂导出Excel，包括文件名以及表名,不创建表头
	 *
	 * @param list
	 *            导出的实体类
	 * @param title
	 *            表头名称
	 * @param sheetName
	 *            sheet表名
	 * @param pojoClass
	 *            映射的实体类
	 * @param fileName
	 * @param response
	 * @return
	 */
	public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName,
                                   ExcelType type, HttpServletResponse response, Integer userMasterId) {
		defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName, type));
	}

	/**
	 * 功能描述：复杂导出Excel，生成在本地，包括文件名以及表名,不创建表头
	 * 
	 * @param list
	 * @param title
	 * @param sheetName
	 * @param pojoClass
	 * @param fileName
	 * @param type
	 * @param localFileOutputStream
	 * @param userMasterId
	 */
	public static void exportExcelLocal(List<?> list, String title, String sheetName, Class<?> pojoClass,
			String fileName, ExcelType type, FileOutputStream localFileOutputStream, Integer userMasterId) {

		Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(title, sheetName, type), pojoClass, list);
		if (workbook != null) {
			downLoadExcelLocal(fileName, localFileOutputStream, workbook);
		}
	}

	/**
	 * 功能描述：Map 集合导出
	 *
	 * @param list
	 *            实体集合
	 * @param fileName
	 *            导出的文件名称
	 * @param response
	 * @return
	 */
	public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
		defaultExport(list, fileName, response);
	}

	/**
	 * 功能描述：默认导出方法
	 *
	 * @param list
	 *            导出的实体集合
	 * @param fileName
	 *            导出的文件名
	 * @param pojoClass
	 *            pojo实体
	 * @param exportParams
	 *            ExportParams封装实体
	 * @param response
	 * @return
	 */
	private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response,
			ExportParams exportParams) {
		Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
		if (workbook != null) {
			downLoadExcel(fileName, response, workbook);
		}
	}

	/**
	 * 功能描述：Excel导出
	 *
	 * @param fileName
	 *            文件名称
	 * @param response
	 * @param workbook
	 *            Excel对象
	 * @return
	 */
	private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
		try {

			if (workbook instanceof HSSFWorkbook) {
				fileName += HSSF;
			} else {
				fileName += XSSF;
			}

			response.setCharacterEncoding("UTF-8");
			response.setHeader("content-Type", "application/vnd.ms-excel");
			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
			workbook.write(response.getOutputStream());

		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 本地生成文件
	 * 
	 * @param fileName
	 * @param localFileOutputStream
	 * @param workbook
	 */
	private static void downLoadExcelLocal(String fileName, FileOutputStream localFileOutputStream, Workbook workbook) {
		try {

			if (workbook instanceof HSSFWorkbook) {
				fileName += HSSF;
			} else {
				fileName += XSSF;
			}

			workbook.write(localFileOutputStream);

		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 功能描述：默认导出方法
	 *
	 * @param list
	 *            导出的实体集合
	 * @param fileName
	 *            导出的文件名
	 * @param response
	 * @return
	 */
	private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
		Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
		if (workbook != null)
			;
		downLoadExcel(fileName, response, workbook);
	}

	/**
	 * 功能描述：根据文件路径来导入Excel
	 *
	 * @param filePath
	 *            文件路径
	 * @param titleRows
	 *            表标题的行数
	 * @param headerRows
	 *            表头行数
	 * @param pojoClass
	 *            Excel实体类
	 * @return
	 */
	public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
		// 判断文件是否存在
		if (StringUtils.isBlank(filePath)) {
			return null;
		}
		ImportParams params = new ImportParams();
		params.setTitleRows(titleRows);
		params.setHeadRows(headerRows);
		List<T> list = null;
		try {
			list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
		} catch (NoSuchElementException e) {
			throw new RuntimeException("模板不能为空");
		} catch (Exception e) {
			e.printStackTrace();

		}
		return list;
	}

	/**
	 * 功能描述：根据接收的Excel文件来导入Excel,并封装成实体类
	 *
	 * @param file
	 *            上传的文件
	 * @param titleRows
	 *            表标题的行数
	 * @param headerRows
	 *            表头行数
	 * @param pojoClass
	 *            Excel实体类
	 * @return
	 */
	public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows,
                                          Class<T> pojoClass) {
		if (file == null) {
			return null;
		}
		ImportParams params = new ImportParams();
		params.setTitleRows(titleRows);
		params.setHeadRows(headerRows);
		List<T> list = null;
		try {
			list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
		} catch (NoSuchElementException e) {
			throw new RuntimeException("excel文件不能为空");
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());

		}
		return list;
	}

	public static void main(String[] args) {

	}

}
